const DyWsClient = require('ws');
const douyinWssInfo = require('./wssInfo'); // 获取抖音 WSS 连接地址
const douyinWssServce = new douyinWssInfo();
const { wsHeaders } = require('./roomInfo')
//工具处理函数
const tools = require('../utils/tool')

//消息解码
const DyProto = require('./protobuf/DyProto.js')
const DyIm = require('./protobuf/DyIm.js') //抖音网站上的代码片段，用于编码WebSocket消息。
const pako = require('pako'); // 用于处理WebSocket消息的压缩和解压。

//队列服务
const { getPAQueue } = require('../nodeQueue/queue.js')
var paQueue = null;

const dyConfig = {
	entryMain: null, //{ksUrl dyUrl wsServer roomId key soure buildStrJSON sendMsg closeSocket consoleLog setGlobalData getGlobalData getClientPool}
	userUniqueId: '',
	roomId: '',
	cookie: '',
	cookieObj: {ttwid: ''},
    wssAddress: '', //抖音wss连接地址
}

class douyinClient {
    //构造函数
    constructor() {
        paQueue = getPAQueue() //初始化队列
    }

    //设置参数
	setConfig(config) {
		if(!config) return this
		Object.assign(dyConfig, config)
		return this
	}

    //启动
	async start() {
        //1.获取 抖音wss连接地址
        douyinWssServce.setConfig({
            liveRoomId: dyConfig.roomId || '', // 直播房间ID
            userUniqueId: dyConfig.userUniqueId || '', // 用户唯一ID
        });
        dyConfig.wssAddress = await douyinWssServce.getWssUrl();
		if(!dyConfig.wssAddress){
            dyConfig.entryMain.sendMsg(dyConfig.entryMain.buildStrJSON(401, `[dy-${dyConfig.entryMain.roomId}]>>>未获取到wssAddress`, '', 'dy'), dyConfig.entryMain.wsServer.clientId);
			return dyConfig.entryMain.consoleLog(`[dy-${dyConfig.entryMain.roomId}]>>>未获取到wssAddress`)
		}
        //2.连接抖音wss
		this.wsClient = new DyWsClient(dyConfig.wssAddress, {
            headers: {
                Cookie: `ttwid=${dyConfig.cookieObj.ttwid}`, // 用户Cookie，用于身份验证和个性化设置。
                ...wsHeaders
            }
        });
        this.wsClient.binaryType = 'arraybuffer';
		this.wsClient.on('open', () => {
            dyConfig.entryMain.setGlobalData('serverConnected', true, dyConfig.entryMain.wsServer.clientId);
			dyConfig.entryMain.setGlobalData('connected', true, dyConfig.entryMain.wsServer.clientId);
            //心跳包定时器
            this.ping();
		})
		this.wsClient.on('close', () => {
			this.stop();
		})
		this.wsClient.on('message', (e) => {
            //服务断开时，关闭
			if(!dyConfig.entryMain.getGlobalData('serverConnected', dyConfig.entryMain.wsServer.clientId)){
				return this.stop();
			}
            const frame = DyProto.PushFrame.deserializeBinary(new Uint8Array(e))
            //1.判断消息是否压缩
            const headers = frame.getHeaderslistList()
            let gzipFlag = false; // 压缩标志，默认为false。如果消息被gzip压缩，则设置为true
            headers.forEach(t => {
                let key = t.getKey(), value = t.getValue();
                if ('compress_type' === key && 'gzip' === value) {
                    gzipFlag = true;
                }
            })
            //解压缩 payload 数据,不解压 frame.getPayload_asU8()
            const payload = !gzipFlag ? frame.getPayload_asU8() : pako.inflate(frame.getPayload()); 
            //2.解析 response 数据
            const response = DyProto.Response.deserializeBinary(payload);
            //websocket 消息答复 ack
            if(response.getNeedack()){
                const ackData = this.getAckData(frame.getLogid(), response.getInternalext());
                this.wsClient.send(ackData)
            }
            //3.解析 response 数据中的消息列表
            const messages = response.getMessageslistList()
            messages.forEach(msg => {
                const msgMethod = msg.getMethod(), msgPayload = msg.getPayload()
                switch(msgMethod) {
                    case 'WebcastChatMessage': //聊天消息
                        paQueue.addTask(() => { //异步执行
                            let parseChatMsg = this.parseChatMsg(msgPayload);
                            if(!parseChatMsg) return;
                            dyConfig.entryMain.sendMsg(
                                dyConfig.entryMain.buildStrJSON(200, 'success',
                                    [parseChatMsg]
                                , 'dy', 'ChatMessage'), dyConfig.entryMain.wsServer.clientId
                            );
                        });
                        break;
                    case 'WebcastGiftMessage': //礼物消息
                        paQueue.addTask(() => { //异步执行
                            let parseGiftMsg = this.parseGiftMsg(msgPayload);
                            if(!parseGiftMsg) return;
                            dyConfig.entryMain.sendMsg(
                                dyConfig.entryMain.buildStrJSON(200, 'success',
                                    [parseGiftMsg]
                                , 'dy', 'GiftMessage'), dyConfig.entryMain.wsServer.clientId
                            );
                        }); 
                        break;
                    case 'WebcastLikeMessage': //点赞消息
                        paQueue.addTask(() => { //异步执行
                            let parseLikeMsg = this.parseLikeMsg(msgPayload);
                            if(!parseLikeMsg) return;
                            dyConfig.entryMain.sendMsg(
                                dyConfig.entryMain.buildStrJSON(200, 'success',
                                    [parseLikeMsg]
                                , 'dy', 'LikeMessage'), dyConfig.entryMain.wsServer.clientId
                            );
                        });
                        break;
                    case 'WebcastMemberMessage': //进入直播间消息
                        paQueue.addTask(() => { //异步执行
                            let parseMemberMsg = this.parseMemberMsg(msgPayload);
                            if(!parseMemberMsg) return;
                            dyConfig.entryMain.sendMsg(
                                dyConfig.entryMain.buildStrJSON(200, 'success',
                                    [parseMemberMsg]
                                , 'dy', 'EnterMessage'), dyConfig.entryMain.wsServer.clientId
                            );
                        });
                        break;
                    case 'WebcastSocialMessage': //关注消息
                        paQueue.addTask(() => { //异步执行
                            let parseSocialMsg = this.parseSocialMsg(msgPayload);
                            if(!parseSocialMsg) return;
                            dyConfig.entryMain.sendMsg(
                                dyConfig.entryMain.buildStrJSON(200, 'success',
                                    [parseSocialMsg]
                                , 'dy', 'FollowMessage'), dyConfig.entryMain.wsServer.clientId
                            );
                        });
                        break;
                    case 'WebcastRoomUserSeqMessage': //直播间统计
                        paQueue.addTask(() => { //异步执行
                            dyConfig.entryMain.sendMsg(
                                dyConfig.entryMain.buildStrJSON(200, 'success',
                                    [this.parseRoomUserSeqMsg(msgPayload)]
                                , 'dy', 'RoomInfoMessage'), dyConfig.entryMain.wsServer.clientId
                            );
                        });
                    break;
                    case 'WebcastFansclubMessage': //粉丝团消息
                        this.parseFansclubMsg(msgPayload)
                        break;
                    case 'WebcastControlMessage': //直播间状态消息
                        this.parseControlMsg(msgPayload)
                        break;
                    case 'WebcastEmojiChatMessage': //聊天表情包消息
                        this.parseEmojiChatMsg(msgPayload)
                        break;
                    case 'WebcastRoomStatsMessage': //直播间统计信息
                        this.parseRoomStatsMsg(msgPayload)
                        break;
                    case 'WebcastRoomMessage': //直播间信息
                        this.parseRoomMsg(msgPayload)
                        break;
                    case 'WebcastRoomRankMessage': //直播间排行榜信息
                        this.parseRankMsg(msgPayload)
                        break;
                    case 'WebcastRoomStreamAdaptationMessage': //直播间流配置
                        this.parseRoomStreamAdaptationMsg(msgPayload)
                        break;
                    default: break;
                }
            })
        })
        this.wsClient.on('error', (e) => {
            dyConfig.entryMain.sendMsg(dyConfig.entryMain.buildStrJSON(401, `[dy-${dyConfig.entryMain.roomId}]>>>连接到抖音wss失败：${e}`, '', 'dy'), dyConfig.entryMain.wsServer.clientId);
            this.stop() //停止
        })
    }

    //停止
	stop(){
		this.timer && clearTimeout(this.timer)
		this.wsClient && this.wsClient.close()
        this.wsClient = null;
        dyConfig.entryMain.setGlobalData('client', null, dyConfig.entryMain.wsServer.clientId);
        dyConfig.entryMain.setGlobalData('connected', false, dyConfig.entryMain.wsServer.clientId);
	}

    //发送心跳包
    ping() {
        this.wsClient && this.wsClient.send(this.getHeartbeatParams())
        this.timer = setTimeout(() => {
            this.wsClient && this.ping()
        }, 10 * 1000)
    }

    //websocket 消息答复
    getAckData(logId, payload) {
        const ackData = DyIm.PushFrame.encode({
            log_id: logId, //消息id
            payload_type: 'ack',
            payload: payload //payload
        }).finish();
        return new Uint8Array(ackData)
    }

    //获取 心跳参数
	getHeartbeatParams() {
        const hbData = DyIm.PushFrame.encode({
            payload_type: 'hb', //固定值
        }).finish();
        return new Uint8Array(hbData)
	}

    //解析聊天消息--------------------------------------------Begin
    parseChatMsg(payload) { //聊天消息
        const msg = DyProto.ChatMessage.deserializeBinary(payload);
        if(!tools.verifyWord(msg.getUser().getNickname() || '')) return null;
        if(!tools.verifyWord(msg.getContent() || '')) return null;
        return {
            uid: msg.getUser().getId() || '', //用户ID
			nickName: msg.getUser().getNickname() || '', //昵称
			avatar: msg.getUser().getAvatarthumb().getUrllistlistList()[0] || '', //头像URL（如果有）
            sex: msg.getUser().getGender() || 0, //性别 1: 男, 2: 女, 0: 未设置
            phone: msg.getUser().getTelephone() || '', //电话号码（如果有）
            content: msg.getContent() || '', //评论内容
        }
    }

    parseGiftMsg(payload) { //礼物消息
        const msg = DyProto.GiftMessage.deserializeBinary(payload);
        if(!tools.verifyWord(msg.getUser().getNickname() || '')) return null;
        if(!tools.verifyWord(msg.getGift().getName() || '')) return null;
        return {
            uid: msg.getUser().getId() || '', //用户ID
			nickName: msg.getUser().getNickname() || '', //昵称
			avatar: msg.getUser().getAvatarthumb().getUrllistlistList()[0] || '', //头像URL（如果有）
            sex: msg.getUser().getGender() || 0, //性别 1: 男, 2: 女, 0: 未设置
            phone: msg.getUser().getTelephone() || '', //电话号码（如果有）
            giftId: msg.getGiftid() || -1, //礼物ID
            giftName: msg.getGift().getName() || '', //礼物名称
            giftCount: msg.getCombocount() || 0, //礼物总数量 
        }
    }

    parseLikeMsg(payload) { //点赞消息
        const msg = DyProto.LikeMessage.deserializeBinary(payload);
        if(!tools.verifyWord(msg.getUser().getNickname() || '')) return null;
        return {
            uid: msg.getUser().getId() || '', //用户ID
			nickName: msg.getUser().getNickname() || '', //昵称
			avatar: msg.getUser().getAvatarthumb().getUrllistlistList()[0] || '', //头像URL（如果有）
            sex: msg.getUser().getGender() || 0, //性别 1: 男, 2: 女, 0: 未设置
            phone: msg.getUser().getTelephone() || '', //电话号码（如果有）
            count: msg.getCount() || 0, //点赞数量
        }
    }

    parseMemberMsg(payload) { //进入直播间消息
        const msg = DyProto.MemberMessage.deserializeBinary(payload);
        if(!tools.verifyWord(msg.getUser().getNickname() || '')) return null;
        return {
            uid: msg.getUser().getId() || '', //用户ID
			nickName: msg.getUser().getNickname() || '', //昵称
			avatar: msg.getUser().getAvatarthumb().getUrllistlistList()[0] || '', //头像URL（如果有）
            sex: msg.getUser().getGender() || 0, //性别 1: 男, 2: 女, 0: 未设置
            phone: msg.getUser().getTelephone() || '', //电话号码（如果有）
        }
    }

    parseSocialMsg(payload) { //关注消息
        const msg = DyProto.SocialMessage.deserializeBinary(payload);
        if(!tools.verifyWord(msg.getUser().getNickname() || '')) return null;
        return {
            uid: msg.getUser().getId() || '', //用户ID
			nickName: msg.getUser().getNickname() || '', //昵称
			avatar: msg.getUser().getAvatarthumb().getUrllistlistList()[0] || '', //头像URL（如果有）
            sex: msg.getUser().getGender() || 0, //性别 1: 男, 2: 女, 0: 未设置
            phone: msg.getUser().getTelephone() || '', //电话号码（如果有）
            followCount: msg.getFollowcount() || 0, //关注总数量
        }
    }

    parseRoomUserSeqMsg(payload) { //直播间统计
        const msg = DyProto.RoomUserSeqMessage.deserializeBinary(payload);
        return {
            watchCount: msg?.getTotalpvforanchor() || 0, //累计观看总数
            currentCount: msg?.getTotal() || 0, //当前观看人数
			likeCount: 0, //点赞总数
        }
    }

    parseFansclubMsg(payload) { //粉丝团消息

    }

    parseControlMsg(payload) { //直播间状态消息

    }

    parseEmojiChatMsg(payload) { //聊天表情包消息

    }

    parseRoomStatsMsg(payload) { //直播间统计信息

    }

    parseRoomMsg(payload) { //直播间信息

    }

    parseRankMsg(payload) { //直播间排行榜信息

    }

    parseRoomStreamAdaptationMsg(payload) { //直播间流配置

    }
    //解析聊天消息--------------------------------------------End

}
module.exports = douyinClient